
use std::rc::Rc;
use std::thread;
use std::sync::{Arc,RwLock,Mutex};
use std::sync::mpsc::channel;
fn main() {

    // rust 建立所有权 要求一个资源同一时刻有且只有一个拥有所有权的绑定或&mut引用
    // 实现方式（Rc和Arc）让程序在同一时刻，实现同一资源的多个所有权拥有者，多个拥有者共享资源。

    // Rc 
    // 用于同一线程内部，通过使用use std::rc::Rc 来引入
    // 1. 用 Rc 包装起来的类型对象，是 immutable 的，即 不可变的。即你无法修改 Rc<T> 中的 T 对象，只能读
    // 2. 一旦最后一个拥有者消失，则资源会被自动回收，这个生命周期是在编译期就确定下来的；
    // 3. Rc 只能用于同一线程内部，不能用于线程之间的对象共享（不能跨线程传递）；
    // 4. Rc 实际上是一个指针，它不影响包裹对象的方法调用形式（即不存在先解开包裹再调用值这一说

    let five = Rc::new(5);
    let five2 = five.clone();
    let five3 = five.clone();

    // Rc  Weak 
    // Weak通过use std::rc::Weak 来引入
    // Rc是一个引用计数指针，而weak是一个指针，但不增加引用计数
    // 1. 可访问，但不拥有，不增加引用计数，因此不会对资源回收管理造成影响
    // 2.可由Rc<T>调用downgrade方法而转换weak<T>
    // 3.weak<T>可以使用upgrade方法转换位option<Rc<T>>,如果资源被释放，则option值为none
    // 4.常用于解决循环引用问题


    let five = Rc::new(5);

    let weak_five = Rc::downgrade(&five);

    let strong_five: Option<Rc<_>> = weak_five.upgrade();

    // Arc
    // Arc是原子引用计数，是Rc的多线程版本，Arc通过std::sync::Arc引入
    // 1.Arc可跨线程传递，用于跨线程共享一个对象
    // 2.用于Arc包裹起来的类型对象，对可变性没有要求
    // 3.一旦最后一个拥有者消失，则资源会被自动回收，生命周期是在编译期就确定下来了
    // 4.Arc实际上是一个指针，它不影响包裹对象的方法调用形式
    // 5.Arc对于多线程的共享状态几乎是必须的

    let numbers: Vec<_> = (0..100u32).collect();
    let shared_numbers = Arc::new(numbers);

    for _ in 0..10 {
        let child_numbers = shared_numbers.clone();

        thread::spawn(move || {
            let local_numbers = &child_numbers[..];

            // Work with the local numbers
        });
    }
    

    // Mutex
    // Mutex意为互斥对象，用来保护共享数据
    // 1.Mutex会等待获取锁令牌，在等待过程中会阻塞线程，直到锁令牌得到，同时只有一个线程的Mutex对象获取锁
    // 2.Mutex通过.lock()或.try_lock()来尝试得到锁令牌，被保护的对象 ，必须通过这两个方法返回的RAII来调用，不能直接操作
    // 3.当RAII守卫作用域结束后，锁会自动解开
    // 4.在多线程中，Mutex一般和Arc配合使用
    let data = Arc::new(Mutex::new(0));

    let (tx, rx) = channel();
    for _ in 0..10 {
        let (data, tx) = (data.clone(), tx.clone());
        thread::spawn(move || {
            // The shared state can only be accessed once the lock is held.
            // Our non-atomic increment is safe because we're the only thread
            // which can access the shared state when the lock is held.
            //
            // We unwrap() the return value to assert that we are not expecting
            // threads to ever fail while holding the lock.
            let mut data = data.lock().unwrap();
            *data += 1;
            if *data == N {
                tx.send(()).unwrap();
            }
            // the lock is unlocked here when `data` goes out of scope.
        });
    }
    rx.recv().unwrap();

    // lock与try_lock的区别：
    // .lock()方法会等待锁令牌，等待的时候会阻塞当前线程，而try_lock方法只会做一个尝试操作不会阻塞当前线程
    // 当.try_lock()没有获取到锁令牌时，会返回err



    // RWLock
    // Rwlock读写锁
    // 1. 同时允许多个读，最多只能一个写
    // 2. 读和写不能同时存在
    let lock = RwLock::new(5);
    {
        let r1 = lock.read().unwrap();
        let r2 = lock.read().unwrap();
        assert_eq!(*r1, 5);
        assert_eq!(*r2, 5);
    }
    
    {
        let mut w = lock.write().unwrap();
        *w += 1;
        assert_eq!(*w, 6);
    } 
    
    // 读写锁的方法
    // .read()
    // .try_read()
    // .write()
    // .try_write()
    // 注意需要对 .try_read() 和 .try_write() 的返回值进行判断。
}